﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Reflection;
using System.Dynamic;
using System.Collections;
using System.ComponentModel;

namespace SEP.Conversion
{
    public partial class Default : System.Web.UI.Page
    {
        #region Fields
        private Dictionary<int, string> propertyMapOld = new Dictionary<int, string>()  {
                                                                                        {0, "Customer"},
                                                                                        {1, "Company"},
                                                                                        {2, "FirstName"},
                                                                                        {3, "LastName"},
                                                                                        {4, "Contact"},
                                                                                        {5, "Phone"},
                                                                                        {6, "Fax"},
                                                                                        {7, "AltPhone"},
                                                                                        {8, "AltContact"},
                                                                                        {9, "Email"},
                                                                                        {10, "BillTo1"},
                                                                                        {11, "BillTo2"},
                                                                                        {12, "BillTo3"},
                                                                                        {13, "BillTo4"},
                                                                                        {14, "BillTo5"},
                                                                                        {15, "ShipTo1"},
                                                                                        {16, "ShipTo2"},
                                                                                        {17, "ShipTo3"},
                                                                                        {18, "ShipTo4"},
                                                                                        {19, "ShipTo5"},
                                                                                        {20, "CustomerType"}
                                                                                    };

        private Dictionary<int, string> propertyMap = new Dictionary<int, string>()  {
                                                                                        {0, "Customer"},
                                                                                        {1, "Contact"},
                                                                                        {2, "Phone"},
                                                                                        {3, "AltPhone"},
                                                                                        {4, "AltContact"},
                                                                                        {5, "Email"},                                                                                                                                                                          
                                                                                        {6, "BillTo1"},
                                                                                        {7, "BillTo2"},
                                                                                        {8, "BillTo3"},
                                                                                        {9, "BillTo4"},
                                                                                        {10, "BillTo5"},
                                                                                        {11, "ShipTo1"},
                                                                                        {12, "ShipTo2"},
                                                                                        {13, "ShipTo3"},
                                                                                        {14, "ShipTo4"},
                                                                                        {15, "ShipTo5"},                                                                                        
                                                                                    };
        #endregion

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                BindInfo();
            }
        }

        private void BindInfo()
        {
            string path = @"C:\SEPCONVERSION\export.csv";

            var exports = new List<ExportedObject>();
            var specialCases = new List<ExportedObject>();

            string[] lines = File.ReadAllLines(path);
            int lineNumber = 0;

            foreach (string l in lines)
            {
                if (lineNumber > 0)
                {
                    string[] parts = l.Split(',');
                    var eo = new ExportedObject();

                    for (int i = 0; i < parts.Length; i++)
                    {
                        MapIndexToProperty(ref eo, i, parts[i]);
                    }

                    if (!string.IsNullOrWhiteSpace(eo.Customer))
                    {
                        eo.BuildConstituent();

                        if (eo.SpecialCase)
                        {
                            specialCases.Add(eo);
                        }
                        else
                        {
                            exports.Add(eo);
                        }
                    }
                }

                lineNumber++;
            }

            lblConvertedCount.Text = string.Format("Total number of correct cases: {0}", exports.Count);
            lblSpecialCaseCount.Text = string.Format("Total number of special cases: {0}", specialCases.Count);

            grvConversion.DataSource = exports;
            grvConversion.DataBind();

            grvSpecialCases.DataSource = specialCases;
            grvSpecialCases.DataBind();

            List<BusinessLogic.Address> addresses = new List<BusinessLogic.Address>();

            ViewState["EXPORTS"] = exports;
            ViewState["SPECIALCASES"] = specialCases;

            foreach (ExportedObject c in exports)
            {
                addresses.AddRange(c.Constituent.Addresses); 
            }

            grvAddresses.DataSource = addresses;
            grvAddresses.DataBind();
        }

        private void MapIndexToProperty(ref ExportedObject eo, int index, string value)
        {
            string propertyName;

            if (propertyMap.TryGetValue(index, out propertyName))
            {
                var propertyInfo = eo.GetType().GetProperty(propertyName);
                propertyInfo.SetValue(eo, Convert.ChangeType(value, propertyInfo.PropertyType), null);
            }
        }

        protected void btnConversion_Click(object sender, EventArgs e)
        {
            var conversionPrepped = false;

            var exports = (List<ExportedObject>)ViewState["EXPORTS"];

            if (exports != null && exports.Count > 0)
            {
                BusinessLogic.Constituent.ConversionPrep();
                                
                conversionPrepped = true;

                foreach (var c in exports)
                {
                    c.Constituent.CreateForConversion(false);
                }
            }

            //var specialCases = (List<ExportedObject>)ViewState["SPECIALCASES"];

            //if(specialCases != null && specialCases.Count > 0)
            //{
            //    if(!conversionPrepped)
            //    {
            //        BusinessLogic.Constituent.ConversionPrep();
            //        conversionPrepped = true;
            //    }

            //    foreach(var c in specialCases)
            //    {                    
            //        if(!string.IsNullOrWhiteSpace(c.ErrorMessage) && c.ErrorMessage.Contains("address"))
            //        {
            //            c.Constituent.CreateForConversion(false, true);
            //        }
            //    }
            //}
        }
    }

    [Serializable()]
    public class ExportedObject
    {
        #region Fields
        private string _Customer;
        //private string _Company;
        private string _FirstName;
        private string _LastName;
        private string _Contact;
        private string _Phone;
        //private string _Fax;
        private string _AltPhone;
        private string _AltContact;
        private string _Email;
        private string _BillTo1;
        private string _BillTo2;
        private string _BillTo3;
        private string _BillTo4;
        private string _BillTo5;
        private string _ShipTo1;
        private string _ShipTo2;
        private string _ShipTo3;
        private string _ShipTo4;
        private string _ShipTo5;
        //private string _CustomerType;
        private BusinessLogic.Constituent _Constituent;
        private bool _SpecialCase = false;
        private string _ErrorMessage;
        #endregion

        #region Constructors
        public ExportedObject() { }

        public ExportedObject(string customer, string company, string firstName, string lastName, string contact, string phone,
                                    string fax, string altPhone, string altContact, string email, string billTo1, string billTo2, string billTo3,
                                    string billTo4, string billTo5, string shipTo1, string shipTo2, string shipTo3, string shipTo4, string shipTo5, string customerType)
        {
            _Customer = customer;
            //_Company = company;
            _FirstName = firstName;
            _LastName = lastName;
            _Contact = contact;
            _Phone = phone;
            //_Fax = fax;
            _AltPhone = altPhone;
            _AltContact = altContact;
            _Email = email;
            _BillTo1 = billTo1;
            _BillTo2 = billTo2;
            _BillTo3 = billTo3;
            _BillTo4 = billTo4;
            _BillTo5 = billTo5;
            _ShipTo1 = shipTo1;
            _ShipTo2 = shipTo2;
            _ShipTo3 = shipTo3;
            _ShipTo4 = shipTo4;
            _ShipTo5 = shipTo5;
            //_CustomerType = customerType;
        }
        #endregion

        public void BuildConstituent()
        {
            try
            {
                _Constituent = new BusinessLogic.Constituent();
                _Constituent.IsService = true;
                _Constituent.IsSales = false;
                _Constituent.IsOrganization = true;
                _Constituent.IsActive = true;
                _Constituent.LastName = this._Customer;

                //primary contact                
                BusinessLogic.Constituent primaryContact = new BusinessLogic.Constituent();
                primaryContact.FirstName = (string.IsNullOrEmpty(this._FirstName) ? "" : this._FirstName);                
                primaryContact.LastName = (string.IsNullOrEmpty(this._LastName) ? "" : this._LastName);

                //phone
                if (!string.IsNullOrWhiteSpace(this._Phone))
                {
                    primaryContact.Phone = new BusinessLogic.Phone();
                    primaryContact.Phone.PhoneType = new BusinessLogic.PhoneType() { ID = new Guid("B26CF097-7960-4D2A-A700-117C634146B8"), Description = "Business 1" };

                    string phone = this._Phone;
                    string ext = string.Empty;

                    if (phone.ToLower().Contains("ext"))
                    {
                        phone = phone.Replace("ext", " ");
                        int index = phone.ToLower().LastIndexOf(" ");
                        ext = phone.Substring(index).Trim();
                        phone = phone.Substring(0, index).Trim();
                    }

                    primaryContact.Phone.Number = phone;
                    primaryContact.Phone.Extension = ext;
                    primaryContact.Phone.IsPrimary = true;
                }

                //primary contact relationship
                if (!string.IsNullOrWhiteSpace(primaryContact.FirstName) || !string.IsNullOrWhiteSpace(primaryContact.LastName))
                {
                    BusinessLogic.Relationship relationship = new BusinessLogic.Relationship();
                    relationship.IsPrimary = true;
                    relationship.RelationshipConstituent = _Constituent;
                    relationship.RelationshipTypeCode = new BusinessLogic.RelationshipType() { ID = new Guid("7E50A565-1EF9-46FA-B4AE-CEB0659D3B06"), Description = "Employer" };
                    relationship.ReciprocalConstituent = primaryContact;
                    relationship.ReciprocalRelationshipTypeCode = new BusinessLogic.RelationshipType() { ID = new Guid("626FDA6A-4876-48B1-944B-FD6EF564C6FD"), Description = "Employee" };
                    primaryContact.Relationships = new List<BusinessLogic.Relationship>();
                    primaryContact.Relationships.Add(relationship);
                }

                //email
                if (!string.IsNullOrWhiteSpace(this._Email))
                {
                    primaryContact.EmailAddress = new BusinessLogic.Email();
                    primaryContact.EmailAddress.EmailAddressType = new BusinessLogic.EmailType() { ID = new Guid("3AF33A92-7336-4E63-BEF0-B448CC2D2F13"), Description = "Business" };
                    primaryContact.EmailAddress.EmailAddress = this._Email;
                    primaryContact.EmailAddress.IsPrimary = true;
                }

                //fax
                //if(!string.IsNullOrWhiteSpace(this._Fax))
                //{
                //    BusinessLogic.Phone fax = new BusinessLogic.Phone();
                //    fax.Number = this._Fax;
                //    fax.PhoneType = new BusinessLogic.PhoneType() { ID = new Guid("F1082F17-0CE4-4839-954E-4AED6B9F6AFA"), Description = "Fax" };
                //    primaryContact.Phones.Add(fax);
                //}

                if (!string.IsNullOrWhiteSpace(_FirstName) && !string.IsNullOrWhiteSpace(_LastName))
                {
                    _Constituent.PrimaryContact = primaryContact;
                }

                //billing address
                if (!string.IsNullOrWhiteSpace(this.BillToAddressBlock))
                {
                    _Constituent.Addresses = new List<BusinessLogic.Address>();

                    BusinessLogic.Address billToAddress = ParseAddress(this.BillToParts);
                    billToAddress.AddressBlock.Replace(_Constituent.Name, "");
                    billToAddress.AddressType = new BusinessLogic.AddressType() { ID = new Guid("FB7FBB83-1D2D-4672-8DEA-B8D9227B725F"), Description = "Bill To" };
                    billToAddress.IsPrimary = false;

                    if (string.IsNullOrWhiteSpace(billToAddress.City) || billToAddress.State == null || string.IsNullOrWhiteSpace(billToAddress.PostCode))
                    {
                        throw new Exception("Billing address is a special case.");
                    }

                    _Constituent.Addresses.Add(billToAddress);
                }

                //shipping address
                if (!string.IsNullOrWhiteSpace(this.ShipToAddressBlock))
                {
                    if (_Constituent.Addresses != null)
                    {
                        _Constituent.Addresses = new List<BusinessLogic.Address>();
                    }

                    BusinessLogic.Address shipToAddress = ParseAddress(this.ShipToParts);
                    shipToAddress.AddressBlock.Replace(_Constituent.Name, "");
                    shipToAddress.AddressType = new BusinessLogic.AddressType() { ID = new Guid("FB7FBB83-1D2D-4672-8DEA-B8D9227B725F"), Description = "Ship To" };

                    if (_Constituent.Address == null)
                    {
                        shipToAddress.IsPrimary = true;
                    }
                    else if (_Constituent.Address.IsPrimary)
                    {
                        _Constituent.Address.IsPrimary = false;
                        shipToAddress.IsPrimary = true;
                    }

                    if (string.IsNullOrWhiteSpace(shipToAddress.City) || shipToAddress.State == null || string.IsNullOrWhiteSpace(shipToAddress.PostCode))
                    {
                        throw new Exception("Shipping address is a special case.");
                    }

                    _Constituent.Addresses.Add(shipToAddress);
                }

                //alternate contact
                if (!string.IsNullOrWhiteSpace(this._AltContact))
                {
                    BusinessLogic.Constituent altContact = new BusinessLogic.Constituent();

                    string[] altContactNameParts = this._AltContact.Split(' ');

                    altContact.FirstName = altContactNameParts[0];

                    if (altContactNameParts.Length > 0)
                    {
                        //just set the last name to the last split part
                        altContact.LastName = altContactNameParts[altContactNameParts.Length - 1];
                    }

                    //BusinessLogic.Relationship relationship = new BusinessLogic.Relationship();
                    //relationship.IsPrimary = false;
                    //relationship.RelationshipConstituent = _Constituent;
                    //relationship.RelationshipTypeCode = new BusinessLogic.RelationshipType() { ID = new Guid("7E50A565-1EF9-46FA-B4AE-CEB0659D3B06"), Description = "Employer" };
                    //relationship.ReciprocalConstituent = altContact;
                    //relationship.ReciprocalRelationshipTypeCode = new BusinessLogic.RelationshipType() { ID = new Guid("626FDA6A-4876-48B1-944B-FD6EF564C6FD"), Description = "Employee" };                                        
                }

                if(primaryContact !=null)
                {
                    _Constituent.PrimaryContact = primaryContact;
                }
            }
            catch (Exception ex)
            {
                this._SpecialCase = true;
                this._ErrorMessage = ex.Message;
                ex = null;
            }
        }

        private BusinessLogic.Address ParseAddress(List<string> addressParts)
        {
            BusinessLogic.Address add = new BusinessLogic.Address();

            int decrementedCount = addressParts.Count - 1;

            if (decrementedCount >= 0)
            {
                if (decrementedCount > 0)
                {
                    string addressBlock = string.Empty;

                    for (int i = 0; i < decrementedCount; i++)
                    {
                        if (string.IsNullOrWhiteSpace(addressBlock))
                        {
                            addressBlock = addressParts[i];
                        }
                        else
                        {
                            addressBlock = string.Concat(addressBlock, Environment.NewLine, addressParts[i]);
                        }
                    }

                    add.AddressBlock = addressBlock;
                }

                var country = new BusinessLogic.Country();
                country.ID = new Guid("C94C3365-FBF6-4E4D-8170-0F5D9F21C398");
                country.Description = "United States of America";
                country.Abbreviation = "USA";

                add.Country = country;

                //last set of address info. hoping
                //its city, state abbreviation, zip
                var lastPart = addressParts[decrementedCount];

                if (!string.IsNullOrWhiteSpace(lastPart))
                {
                    if (lastPart.Contains("Attn"))
                    {
                        add.AddressBlock = string.Concat(lastPart, Environment.NewLine, add.AddressBlock);

                        try
                        {
                            lastPart = addressParts[decrementedCount - 1];
                            add.AddressBlock = add.AddressBlock.Replace(string.Concat("\r\n", lastPart), "");
                        }
                        catch { }
                    }

                    lastPart = lastPart.Trim();

                    string[] parts = lastPart.Split(' ');

                    foreach (string s in parts)
                    {
                        if (!string.IsNullOrWhiteSpace(s))
                        {
                            bool used = false;

                            //state
                            if (s.Trim().Length.Equals(2))
                            {
                                add.State = new BusinessLogic.State() { Abbreviation = s.Trim() };
                                used = true;
                            }

                            //zip code
                            if (!used)
                            {
                                var x = s.Replace("-", "");
                                var zip = 0;

                                if (int.TryParse(x, out zip))
                                {
                                    add.PostCode = zip.ToString();
                                    used = true;
                                }
                            }

                            //city
                            if (!used)
                            {
                                add.City = s;
                            }
                        }
                    }

                    if (!string.IsNullOrWhiteSpace(add.PostCode) && string.IsNullOrWhiteSpace(add.City))
                    {
                        lastPart = addressParts[decrementedCount - 2];

                        parts = lastPart.Split(' ');

                        foreach (string s in parts)
                        {
                            if (!string.IsNullOrWhiteSpace(s))
                            {
                                bool used = false;

                                //state
                                if (s.Trim().Length.Equals(2))
                                {
                                    add.State = new BusinessLogic.State() { Abbreviation = s.Trim() };
                                    used = true;
                                }

                                //city
                                if (!used)
                                {
                                    add.City = s;
                                }
                            }
                        }
                    }
                }
            }

            return add;
        }

        public BusinessLogic.Constituent Constituent
        {
            get
            {
                return _Constituent;
            }
        }

        public string Customer
        {
            get
            {
                return _Customer;
            }
            set
            {
                _Customer = value;
            }
        }

        //public string Company
        //{
        //    get
        //    {
        //        return _Company;
        //    }
        //    set
        //    {
        //        _Company = value;
        //    }
        //}

        public string FirstName
        {
            get
            {
                return _FirstName;
            }
            set
            {
                _FirstName = value;
            }
        }

        public string LastName
        {
            get
            {
                return _LastName;
            }
            set
            {
                _LastName = value;
            }
        }

        public string Contact
        {
            get
            {
                return _Contact;
            }
            set
            {
                string contact = value;

                if (string.IsNullOrWhiteSpace(_FirstName) && string.IsNullOrWhiteSpace(_LastName))
                {
                    string prefix = string.Empty;
                    string[] parts = contact.Trim().Split(' ');

                    if(parts.Count().Equals(3))
                    {
                        if(parts[0].Equals("Dr."))
                        {
                            prefix = parts[0];
                        }
                    }

                    if(!string.IsNullOrEmpty(prefix))
                    {
                        contact = contact.Replace(prefix, "").Trim();
                    }

                    if (contact.IndexOf(" ").Equals(contact.LastIndexOf(" ")))
                    {
                        int index = contact.LastIndexOf(" ");
                        int length = contact.Length - index;

                        if (index > 0)
                        {
                            _FirstName = contact.Substring(0, index);
                            _LastName = contact.Substring(index, length);
                        }
                        else if (contact.Length > 0)
                        {
                            _FirstName = contact;
                        }

                        _FirstName = string.Concat(prefix, " ", _FirstName);
                    }
                    else
                    {
                        _SpecialCase = true;
                    }
                }

                _Contact = contact;
            }
        }

        public string Phone
        {
            get
            {
                return _Phone;
            }
            set
            {
                _Phone = value;
            }
        }

        //public string Fax
        //{
        //    get
        //    {
        //        return _Fax;
        //    }
        //    set
        //    {
        //        _Fax = value;
        //    }
        //}

        public string AltPhone
        {
            get
            {
                return _AltPhone;
            }
            set
            {
                _AltPhone = value;
            }
        }

        public string AltContact
        {
            get
            {
                return _AltContact;
            }
            set
            {
                _AltContact = value;
            }
        }

        public string Email
        {
            get
            {
                return _Email;
            }
            set
            {
                _Email = value;
            }
        }

        public string BillTo1
        {
            get
            {
                return _BillTo1;
            }
            set
            {
                _BillTo1 = value;
            }
        }

        public string BillTo2
        {
            get
            {
                return _BillTo2;
            }
            set
            {
                _BillTo2 = value;
            }
        }

        public string BillTo3
        {
            get
            {
                return _BillTo3;
            }
            set
            {
                _BillTo3 = value;
            }
        }

        public string BillTo4
        {
            get
            {
                return _BillTo4;
            }
            set
            {
                _BillTo4 = value;
            }
        }

        public string BillTo5
        {
            get
            {
                return _BillTo5;
            }
            set
            {
                _BillTo5 = value;
            }
        }

        public string BillToAddressBlock
        {
            get
            {
                var parts = new List<string>();
                parts.Add(_BillTo1);
                parts.Add(Environment.NewLine);
                parts.Add(_BillTo2);
                parts.Add(Environment.NewLine);
                parts.Add(_BillTo3);
                parts.Add(Environment.NewLine);
                parts.Add(_BillTo4);
                parts.Add(Environment.NewLine);
                parts.Add(_BillTo5);

                return string.Concat(parts);
            }
        }

        public List<string> BillToParts
        {
            get
            {
                List<string> parts = new List<string>();
                parts.Add(this._BillTo1);
                parts.Add(this._BillTo2);
                parts.Add(this._BillTo3);
                parts.Add(this._BillTo4);
                parts.Add(this._BillTo5);
                parts.RemoveAll(x => string.IsNullOrWhiteSpace(x));

                return parts;
            }
        }

        public string ShipTo1
        {
            get
            {
                return _ShipTo1;
            }
            set
            {
                _ShipTo1 = value;
            }
        }

        public string ShipTo2
        {
            get
            {
                return _ShipTo2;
            }
            set
            {
                _ShipTo2 = value;
            }
        }

        public string ShipTo3
        {
            get
            {
                return _ShipTo3;
            }
            set
            {
                _ShipTo3 = value;
            }
        }

        public string ShipTo4
        {
            get
            {
                return _ShipTo4;
            }
            set
            {
                _ShipTo4 = value;
            }
        }

        public string ShipTo5
        {
            get
            {
                return _ShipTo5;
            }
            set
            {
                _ShipTo5 = value;
            }
        }

        public string ShipToAddressBlock
        {
            get
            {
                var parts = new List<string>();
                parts.Add(_ShipTo1);
                parts.Add(Environment.NewLine);
                parts.Add(_ShipTo2);
                parts.Add(Environment.NewLine);
                parts.Add(_ShipTo3);
                parts.Add(Environment.NewLine);
                parts.Add(_ShipTo4);
                parts.Add(Environment.NewLine);
                parts.Add(_ShipTo5);

                return string.Concat(parts);
            }
        }

        public List<string> ShipToParts
        {
            get
            {
                List<string> parts = new List<string>();
                parts.Add(this._ShipTo1);
                parts.Add(this._ShipTo2);
                parts.Add(this._ShipTo3);
                parts.Add(this._ShipTo4);
                parts.Add(this._ShipTo5);
                parts.RemoveAll(x => string.IsNullOrWhiteSpace(x));

                return parts;
            }
        }

        //public string CustomerType
        //{
        //    get
        //    {
        //        return _CustomerType;
        //    }
        //    set
        //    {
        //        _CustomerType = value;
        //    }
        //}

        public bool SpecialCase
        {
            get
            {
                return _SpecialCase;
            }
            set
            {
                _SpecialCase = value;
            }
        }

        public string ErrorMessage
        {
            get
            {
                return _ErrorMessage;
            }
            set
            {
                _ErrorMessage = value;  
            }
        }
    }
}